"""
Markdown文件保存工具 - 用于将Markdown内容保存到本地文件
"""
import os
import re
import uuid
from datetime import datetime
from pathlib import Path
from typing import Optional, Union
import logging

logger = logging.getLogger(__name__)

class MarkdownSaver:
    def __init__(self, output_dir: str = ".", max_filename_length: int = 100):
        """
        初始化Markdown文件保存器
        
        Args:
            output_dir: 输出目录路径，默认为当前目录
            max_filename_length: 文件名最大长度
        """
        self.output_dir = Path(output_dir)
        self.max_filename_length = max_filename_length
        self._ensure_output_dir()
    
    def _ensure_output_dir(self):
        """确保输出目录存在"""
        try:
            self.output_dir.mkdir(parents=True, exist_ok=True)
            logger.info(f"输出目录已就绪: {self.output_dir.absolute()}")
        except Exception as e:
            logger.error(f"创建输出目录失败: {e}")
            raise
    
    def _generate_filename(self, title: Optional[str] = None, url: Optional[str] = None) -> str:
        """
        生成有效的文件名
        
        Args:
            title: 文章标题
            url: 源URL
            
        Returns:
            生成的文件名（不含扩展名）
        """
        # 如果有标题，使用标题作为文件名基础
        if title:
            # 清理标题中的非法文件名字符
            clean_title = re.sub(r'[<>:"/\\|?*]', '', title)
            clean_title = clean_title.replace(' ', '_')
            clean_title = clean_title.strip('_.')
            
            # 截断过长的文件名
            if len(clean_title) > self.max_filename_length:
                clean_title = clean_title[:self.max_filename_length]
            
            if clean_title:  # 确保清理后不是空字符串
                return clean_title
        
        # 如果没有标题或清理后为空，使用URL或时间戳
        if url:
            # 从URL提取域名和路径作为文件名
            from urllib.parse import urlparse
            parsed_url = urlparse(url)
            domain = parsed_url.netloc.replace('.', '_')
            path = parsed_url.path.replace('/', '_').strip('_')
            if path:
                filename = f"{domain}_{path}"
            else:
                filename = domain
        else:
            # 最后 resort：使用时间戳和UUID
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"article_{timestamp}_{uuid.uuid4().hex[:8]}"
        
        # 清理文件名
        filename = re.sub(r'[<>:"/\\|?*]', '', filename)
        filename = filename.strip('_.')
        
        if len(filename) > self.max_filename_length:
            filename = filename[:self.max_filename_length]
        
        return filename
    
    def save_markdown(
        self,
        content: str,
        title: Optional[str] = None,
        url: Optional[str] = None,
        filename: Optional[str] = None,
        metadata: Optional[dict] = None
    ) -> Optional[Path]:
        """
        保存Markdown内容到文件
        
        Args:
            content: Markdown内容
            title: 文章标题（用于生成文件名）
            url: 源URL（用于生成文件名）
            filename: 指定文件名（如果不指定则自动生成）
            metadata: 元数据（会添加到文件头部）
            
        Returns:
            保存的文件路径，如果失败则返回None
        """
        try:
            # 生成或使用指定的文件名
            if filename:
                # 确保文件名有.md扩展名
                if not filename.lower().endswith('.md'):
                    filename += '.md'
                file_stem = filename
            else:
                file_stem = self._generate_filename(title, url) + '.md'
            
            file_path = self.output_dir / file_stem
            
            # 避免文件名冲突
            counter = 1
            original_stem = file_path.stem
            while file_path.exists():
                file_path = self.output_dir / f"{original_stem}_{counter}.md"
                counter += 1
            
            # 准备要写入的内容
            content_to_write = self._prepare_content(content, title, url, metadata)
            
            # 写入文件
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content_to_write)
            
            logger.info(f"Markdown文件已保存: {file_path.absolute()}")
            return file_path
            
        except Exception as e:
            logger.error(f"保存Markdown文件失败: {e}")
            return None
    
    def _prepare_content(
        self,
        content: str,
        title: Optional[str] = None,
        url: Optional[str] = None,
        metadata: Optional[dict] = None
    ) -> str:
        """
        准备要写入文件的内容，添加元信息头
        
        Args:
            content: 原始Markdown内容
            title: 标题
            url: 源URL
            metadata: 额外元数据
            
        Returns:
            格式化后的内容
        """
        # 创建元信息头
        header_lines = []
        
        if title:
            header_lines.append(f"# {title}")
            header_lines.append("")  # 空行
        
        # 添加元数据块
        header_lines.append("---")
        if title:
            header_lines.append(f"title: {title}")
        if url:
            header_lines.append(f"source_url: {url}")
        header_lines.append(f"save_time: {datetime.now().isoformat()}")
        
        # 添加额外的元数据
        if metadata:
            for key, value in metadata.items():
                if value:  # 只添加非空值
                    header_lines.append(f"{key}: {value}")
        
        header_lines.append("---")
        header_lines.append("")  # 空行
        
        header = "\n".join(header_lines)
        return f"{header}{content}"

    def _extract_domain(self, url: str) -> str:
        """从URL提取域名"""
        from urllib.parse import urlparse
        try:
            return urlparse(url).netloc.replace('.', '_')
        except:
            return "unknown"

# 工具函数
def save_markdown_file(
    content: str,
    output_path: Union[str, Path] = ".",
    filename: Optional[str] = None,
    **kwargs
) -> Optional[Path]:
    """
    快速保存Markdown文件的工具函数
    
    Args:
        content: Markdown内容
        output_path: 输出路径或目录
        filename: 文件名（可选）
        **kwargs: 传递给MarkdownSaver的其他参数
        
    Returns:
        保存的文件路径
    """
    output_path = Path(output_path)
    
    # 如果output_path是文件路径而不是目录
    if output_path.suffix:
        save_dir = output_path.parent
        filename = output_path.name
    else:
        save_dir = output_path
        filename = filename
    
    saver = MarkdownSaver(output_dir=save_dir)
    return saver.save_markdown(content, filename=filename, **kwargs)